package com.tsing.cedap.rest.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tsing.cedap.common.exceptions.BusinessException;
import com.tsing.cedap.common.exceptions.CommonException;
import com.tsing.cedap.common.vo.PageResult;
import com.tsing.cedap.rest.entity.*;
import com.tsing.cedap.rest.mapper.*;
import com.tsing.cedap.rest.service.IWebSchoolService;
import com.tsing.cedap.rest.vo.reqVo.*;
import com.tsing.cedap.rest.vo.respVo.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author TheTsing
 * @create 2022-03-29 11:14
 */
@Service
public class WebSchoolServiceImpl implements IWebSchoolService {

    @Resource
    private SchoolMapper schoolMapper;

    @Resource
    private CampusMapper campusMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private CollegeMapper collegeMapper;

    @Resource
    private CourierStationMapper courierStationMapper;

    @Resource
    private ReceivingAddressMapper receivingAddressMapper;

    @Resource
    private ExpressBrandMapper expressBrandMapper;

    @Resource
    private OrderMapper orderMapper;

    @Override
    public void addSchool(SchoolReqVo reqVo) {
        if (ObjectUtil.isNotNull(new LambdaQueryChainWrapper<>(schoolMapper)
                .select(SchoolEntity::getId)
                .eq(SchoolEntity::getName, reqVo.getName())
                .last("LIMIT 1")
                .one())) {
            throw new BusinessException(CommonException.Proxy.SCHOOL_NAME_IS_NOTNULL);
        }
        SchoolEntity schoolEntity = new SchoolEntity();
        BeanUtil.copyProperties(reqVo, schoolEntity);
        schoolMapper.insert(schoolEntity);
    }

    @Override
    public void deleteSchool(IdsReqVo reqVo) {
        if (CollUtil.isNotEmpty(new LambdaQueryChainWrapper<>(campusMapper)
                .select(CampusEntity::getId)
                .in(CampusEntity::getSchoolId, reqVo.getIds())
                .list())) {
            throw new BusinessException(CommonException.Proxy.SCHOOL_NAME_IS_REFERENCE);
        }
        schoolMapper.deleteBatchIds(reqVo.getIds());
    }

    @Override
    public SchoolRespVo getSchool(CodeReqVo reqVo) {
        SchoolEntity schoolEntity = schoolMapper.selectById(reqVo.getCode());
        SchoolRespVo schoolRespVo = new SchoolRespVo();
        BeanUtil.copyProperties(schoolEntity, schoolRespVo);
        return schoolRespVo;
    }

    @Override
    public void updateSchool(SchoolReqVo reqVo) {
        if (ObjectUtil.isNotNull(new LambdaQueryChainWrapper<>(schoolMapper)
                .select(SchoolEntity::getId)
                .eq(SchoolEntity::getName, reqVo.getName())
                .ne(SchoolEntity::getId, reqVo.getId())
                .last("LIMIT 1")
                .one())) {
            throw new BusinessException(CommonException.Proxy.SCHOOL_NAME_IS_NOTNULL);
        }
        SchoolEntity schoolEntity = new SchoolEntity();
        BeanUtil.copyProperties(reqVo, schoolEntity);
        schoolMapper.updateById(schoolEntity);
    }

    @Override
    public PageResult<SchoolRespVo> schoolPage(NameAndPhonePageReqVo reqVo) {
        IPage<SchoolRespVo> page = new Page<>(reqVo.getPageNum(), reqVo.getPageSize());
        List<SchoolRespVo> schoolRespVos = schoolMapper.schoolPage(page, reqVo);
        for (SchoolRespVo schoolRespVo : schoolRespVos) {
            schoolRespVo.setCampusCount(new LambdaQueryChainWrapper<>(campusMapper).select(CampusEntity::getId).eq(CampusEntity::getSchoolId, schoolRespVo.getId()).count())
                    .setCollegeCount(schoolMapper.collegeCount(schoolRespVo.getId()))
                    .setCourierStationCount(schoolMapper.courierStationCount(schoolRespVo.getId()))
                    .setUserCount(schoolMapper.userCount(schoolRespVo.getId()))
                    .setRiderCount(schoolMapper.riderCount(schoolRespVo.getId()));
        }
        return new PageResult<>(page, schoolRespVos);
    }

    @Override
    public void addCampus(CampusReqVo reqVo) {
        if (ObjectUtil.isNotNull(new LambdaQueryChainWrapper<>(campusMapper)
                .select(CampusEntity::getId)
                .eq(CampusEntity::getName, reqVo.getName())
                .eq(CampusEntity::getSchoolId, reqVo.getSchoolId())
                .last("LIMIT 1")
                .one())) {
            throw new BusinessException(CommonException.Proxy.CAMPUS_NAME_IS_NOTNULL);
        }
        CampusEntity campusEntity = new CampusEntity();
        BeanUtil.copyProperties(reqVo, campusEntity);
        campusMapper.insert(campusEntity);
    }

    @Override
    public void deleteCampus(IdsReqVo reqVo) {
        if (CollUtil.isNotEmpty(new LambdaQueryChainWrapper<>(collegeMapper)
                .select(CollegeEntity::getId)
                .in(CollegeEntity::getCampusId, reqVo.getIds())
                .list())) {
            throw new BusinessException(CommonException.Proxy.CAMPUS_NAME_IS_REFERENCE);
        }
        if (CollUtil.isNotEmpty(new LambdaQueryChainWrapper<>(courierStationMapper)
                .select(CourierStationEntity::getId)
                .in(CourierStationEntity::getCampusId, reqVo.getIds())
                .list())) {
            throw new BusinessException(CommonException.Proxy.CAMPUS_NAME_IS_REFERENCE2);
        }
        if (CollUtil.isNotEmpty(new LambdaQueryChainWrapper<>(receivingAddressMapper)
                .select(ReceivingAddressEntity::getId)
                .in(ReceivingAddressEntity::getCampusId, reqVo.getIds())
                .list())) {
            throw new BusinessException(CommonException.Proxy.CAMPUS_NAME_IS_REFERENCE3);
        }
        campusMapper.deleteBatchIds(reqVo.getIds());
    }

    @Override
    public CampusRespVo getCampus(CodeReqVo reqVo) {
        CampusEntity campusEntity = campusMapper.selectById(reqVo.getCode());
        CampusRespVo campusRespVo = new CampusRespVo();
        BeanUtil.copyProperties(campusEntity, campusRespVo);
        return campusRespVo;
    }

    @Override
    public void updateCampus(CampusReqVo reqVo) {
        if (ObjectUtil.isNotNull(new LambdaQueryChainWrapper<>(campusMapper)
                .select(CampusEntity::getId)
                .eq(CampusEntity::getName, reqVo.getName())
                .eq(CampusEntity::getSchoolId, reqVo.getSchoolId())
                .ne(CampusEntity::getId, reqVo.getId())
                .last("LIMIT 1")
                .one())) {
            throw new BusinessException(CommonException.Proxy.CAMPUS_NAME_IS_NOTNULL);
        }
        CampusEntity campusEntity = new CampusEntity();
        BeanUtil.copyProperties(reqVo, campusEntity);
        campusMapper.updateById(campusEntity);
    }

    @Override
    public PageResult<CampusRespVo> campusPage(NameAndPhonePageReqVo reqVo) {
        IPage<CampusRespVo> page = new Page<>(reqVo.getPageNum(), reqVo.getPageSize());
        List<CampusRespVo> campusRespVos = schoolMapper.campusPage(page, reqVo);
        for (CampusRespVo campusRespVo : campusRespVos) {
            campusRespVo.setCollegeCount(new LambdaQueryChainWrapper<>(collegeMapper).select(CollegeEntity::getId).eq(CollegeEntity::getCampusId, campusRespVo.getId()).count())
                    .setCourierStationCount(new LambdaQueryChainWrapper<>(courierStationMapper).select(CourierStationEntity::getId).eq(CourierStationEntity::getCampusId, campusRespVo.getId()).count())
                    .setUserCount(schoolMapper.userCount2(campusRespVo.getId()))
                    .setRiderCount(schoolMapper.riderCount2(campusRespVo.getId()));
        }
        return new PageResult<>(page, campusRespVos);
    }

    @Override
    public void addCollege(CollegeReqVo reqVo) {
        if (ObjectUtil.isNotNull(new LambdaQueryChainWrapper<>(collegeMapper)
                .select(CollegeEntity::getId)
                .eq(CollegeEntity::getName, reqVo.getName())
                .eq(CollegeEntity::getCampusId, reqVo.getCampusId())
                .last("LIMIT 1")
                .one())) {
            throw new BusinessException(CommonException.Proxy.COLLEGE_NAME_IS_NOTNULL);
        }
        CollegeEntity collegeEntity = new CollegeEntity();
        BeanUtil.copyProperties(reqVo, collegeEntity);
        collegeMapper.insert(collegeEntity);
    }

    @Override
    public void deleteCollege(IdsReqVo reqVo) {
        if (CollUtil.isNotEmpty(new LambdaQueryChainWrapper<>(userMapper)
                .select(UserEntity::getId)
                .in(UserEntity::getCollegeId, reqVo.getIds())
                .list())) {
            throw new BusinessException(CommonException.Proxy.COLLEGE_NAME_IS_REFERENCE);
        }
        collegeMapper.deleteBatchIds(reqVo.getIds());
    }

    @Override
    public CollegeRespVo getCollege(CodeReqVo reqVo) {
        return collegeMapper.getCollege(reqVo.getCode());
    }

    @Override
    public void updateCollege(CollegeReqVo reqVo) {
        if (ObjectUtil.isNotNull(new LambdaQueryChainWrapper<>(collegeMapper)
                .select(CollegeEntity::getId)
                .eq(CollegeEntity::getName, reqVo.getName())
                .eq(CollegeEntity::getCampusId, reqVo.getCampusId())
                .ne(CollegeEntity::getId, reqVo.getId())
                .last("LIMIT 1")
                .one())) {
            throw new BusinessException(CommonException.Proxy.COLLEGE_NAME_IS_NOTNULL);
        }
        CollegeEntity collegeEntity = new CollegeEntity();
        BeanUtil.copyProperties(reqVo, collegeEntity);
        collegeMapper.updateById(collegeEntity);
    }

    @Override
    public PageResult<CollegeRespVo> collegePage(NameAndPhonePageReqVo reqVo) {
        IPage<CollegeRespVo> page = new Page<>(reqVo.getPageNum(), reqVo.getPageSize());
        List<CollegeRespVo> collegeRespVos = schoolMapper.collegePage(page, reqVo);
        for (CollegeRespVo collegeRespVo : collegeRespVos) {
            collegeRespVo.setUserCount(new LambdaQueryChainWrapper<>(userMapper).select(UserEntity::getId).eq(UserEntity::getCollegeId, collegeRespVo.getId()).count())
                    .setRiderCount(new LambdaQueryChainWrapper<>(userMapper).select(UserEntity::getId).eq(UserEntity::getCollegeId, collegeRespVo.getId()).eq(UserEntity::getIsRider, 2).count());
        }
        return new PageResult<>(page, collegeRespVos);
    }

    @Override
    public void addStation(StationReqVo reqVo) {
        if (ObjectUtil.isNotNull(new LambdaQueryChainWrapper<>(courierStationMapper)
                .select(CourierStationEntity::getId)
                .eq(CourierStationEntity::getName, reqVo.getName())
                .last("LIMIT 1")
                .one())) {
            throw new BusinessException(CommonException.Proxy.STATION_NAME_IS_NOTNULL);
        }
        CourierStationEntity courierStationEntity = new CourierStationEntity();
        BeanUtil.copyProperties(reqVo, courierStationEntity);
        courierStationMapper.insert(courierStationEntity);
    }

    @Override
    public void deleteStation(IdsReqVo reqVo) {
        if (CollUtil.isNotEmpty(new LambdaQueryChainWrapper<>(expressBrandMapper)
                .select(ExpressBrandEntity::getId)
                .in(ExpressBrandEntity::getCourierStationId, reqVo.getIds())
                .list())) {
            throw new BusinessException(CommonException.Proxy.STATION_NAME_IS_REFERENCE);
        }
        courierStationMapper.deleteBatchIds(reqVo.getIds());
    }

    @Override
    public StationRespVo getStation(CodeReqVo reqVo) {
        return courierStationMapper.getStation(reqVo.getCode());
    }

    @Override
    public void updateStation(StationReqVo reqVo) {
        if (ObjectUtil.isNotNull(new LambdaQueryChainWrapper<>(courierStationMapper)
                .select(CourierStationEntity::getId)
                .eq(CourierStationEntity::getName, reqVo.getName())
                .ne(CourierStationEntity::getId, reqVo.getId())
                .last("LIMIT 1")
                .one())) {
            throw new BusinessException(CommonException.Proxy.STATION_NAME_IS_NOTNULL);
        }
        CourierStationEntity courierStationEntity = new CourierStationEntity();
        BeanUtil.copyProperties(reqVo, courierStationEntity);
        courierStationMapper.updateById(courierStationEntity);
    }

    @Override
    public PageResult<StationRespVo> stationPage(NameAndPhonePageReqVo reqVo) {
        IPage<StationRespVo> page = new Page<>(reqVo.getPageNum(), reqVo.getPageSize());
        List<StationRespVo> collegeRespVos = schoolMapper.stationPage(page, reqVo);
        collegeRespVos.stream().map(e -> e.setTakePartCount(schoolMapper.takePartCount(e.getId()))).collect(Collectors.toList());
        return new PageResult<>(page, collegeRespVos);
    }

    @Override
    public void addBrand(BrandReqVo reqVo) {
        if (ObjectUtil.isNotNull(new LambdaQueryChainWrapper<>(expressBrandMapper)
                .select(ExpressBrandEntity::getId)
                .eq(ExpressBrandEntity::getName, reqVo.getName())
                .eq(ExpressBrandEntity::getCourierStationId, reqVo.getCourierStationId())
                .last("LIMIT 1")
                .one())) {
            throw new BusinessException(CommonException.Proxy.BRAND_NAME_IS_NOTNULL);
        }
        ExpressBrandEntity expressBrandEntity = new ExpressBrandEntity();
        BeanUtil.copyProperties(reqVo, expressBrandEntity);
        expressBrandMapper.insert(expressBrandEntity);
    }

    @Override
    public void deleteBrand(IdsReqVo reqVo) {
        if (CollUtil.isNotEmpty(new LambdaQueryChainWrapper<>(orderMapper)
                .select(OrderEntity::getId)
                .in(OrderEntity::getExpressBrandId, reqVo.getIds())
                .list())) {
            throw new BusinessException(CommonException.Proxy.BRAND_NAME_IS_REFERENCE);
        }
        expressBrandMapper.deleteBatchIds(reqVo.getIds());
    }

    @Override
    public BrandRespVo getBrand(CodeReqVo reqVo) {
        return expressBrandMapper.getBrand(reqVo.getCode());
    }

    @Override
    public void updateBrand(BrandReqVo reqVo) {
        if (ObjectUtil.isNotNull(new LambdaQueryChainWrapper<>(expressBrandMapper)
                .select(ExpressBrandEntity::getId)
                .eq(ExpressBrandEntity::getName, reqVo.getName())
                .eq(ExpressBrandEntity::getCourierStationId, reqVo.getCourierStationId())
                .ne(ExpressBrandEntity::getId, reqVo.getId())
                .last("LIMIT 1")
                .one())) {
            throw new BusinessException(CommonException.Proxy.BRAND_NAME_IS_NOTNULL);
        }
        ExpressBrandEntity expressBrandEntity = new ExpressBrandEntity();
        BeanUtil.copyProperties(reqVo, expressBrandEntity);
        expressBrandMapper.updateById(expressBrandEntity);
    }

    @Override
    public PageResult<BrandRespVo> brandPage(NameAndPhonePageReqVo reqVo) {
        IPage<BrandRespVo> page = new Page<>(reqVo.getPageNum(), reqVo.getPageSize());
        List<BrandRespVo> brandRespVos = schoolMapper.brandPage(page, reqVo);
        brandRespVos.stream().map(e -> e.setTakePartCount(new LambdaQueryChainWrapper<>(orderMapper).select(OrderEntity::getId).eq(OrderEntity::getExpressBrandId, e.getId()).count())).collect(Collectors.toList());
        return new PageResult<>(page, brandRespVos);
    }

}
